/*
 * Original source here:
 *
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package it.gmariotti.cardslib.demo.utils;

import ohos.agp.components.*;
import ohos.agp.database.DataSetSubscriber;
import ohos.app.Context;
import ohos.utils.PlainArray;

import java.util.Arrays;
import java.util.Comparator;

public class SimpleSectionedListAdapter extends BaseItemProvider {
    private boolean mValid = true;
    private int mSectionResourceId;
    private LayoutScatter mLayoutScatter;
    private BaseItemProvider mBaseAdapter;
    private PlainArray<Section> mSections = new PlainArray<>();

    public static class Section {
        int firstPosition;
        int sectionedPosition;
        CharSequence title;

        public Section(int firstPosition, CharSequence title) {
            this.firstPosition = firstPosition;
            this.title = title;
        }

        public CharSequence getTitle() {
            return title;
        }
    }

    public SimpleSectionedListAdapter(Context context, int sectionResourceId,
                                      BaseItemProvider baseAdapter) {
        mLayoutScatter = LayoutScatter.getInstance(context);
        mSectionResourceId = sectionResourceId;
        mBaseAdapter = baseAdapter;
        mBaseAdapter.addDataSubscriber(new DataSetSubscriber() {
            @Override
            public void onChanged() {
                super.onChanged();
                mValid = (mBaseAdapter != null);
                notifyDataChanged();
            }

            @Override
            public void onInvalidated() {
                super.onInvalidated();
                mValid = false;
                notifyDataInvalidated();
            }
        });
    }

    public void setSections(Section[] sections) {
        mSections.clear();

        Arrays.sort(sections, (o, o1) -> (o.firstPosition == o1.firstPosition)
                ? 0
                : ((o.firstPosition < o1.firstPosition) ? -1 : 1));

        int offset = 0; // offset positions for the headers we're adding
        for (Section section : sections) {
            section.sectionedPosition = section.firstPosition + offset;
            mSections.append(section.sectionedPosition, section);
            ++offset;
        }

        notifyDataChanged();
    }

    public int positionToSectionedPosition(int position) {
        int offset = 0;
        for (int i = 0; i < mSections.size(); i++) {
            if (mSections.valueAt(i).firstPosition > position) {
                break;
            }
            ++offset;
        }
        return position + offset;
    }

    public int sectionedPositionToPosition(int sectionedPosition) {
        if (isSectionHeaderPosition(sectionedPosition)) {
            return ListContainer.INVALID_INDEX;
        }

        int offset = 0;
        for (int i = 0; i < mSections.size(); i++) {
            if (mSections.valueAt(i).sectionedPosition > sectionedPosition) {
                break;
            }
            --offset;
        }
        return sectionedPosition + offset;
    }

    public boolean isSectionHeaderPosition(int position) {
        return mSections.get(position) != null;
    }

    @Override
    public int getCount() {
        return (mValid ? mBaseAdapter.getCount() + mSections.size() : 0);
    }

    @Override
    public Object getItem(int position) {
        return isSectionHeaderPosition(position)
                ? mSections.get(position)
                : mBaseAdapter.getItem(sectionedPositionToPosition(position));
    }

    @Override
    public long getItemId(int position) {
        return isSectionHeaderPosition(position)
                ? Integer.MAX_VALUE - mSections.indexOfKey(position)
                : mBaseAdapter.getItemId(sectionedPositionToPosition(position));
    }

    @Override
    public int getItemComponentType(int position) {
        return isSectionHeaderPosition(position)
                ? getComponentTypeCount() - 1
                : mBaseAdapter.getItemComponentType(position);
    }

    //TODO
//    @Override
//    public boolean isEnabled(int position) {
//        //noinspection SimplifiableConditionalExpression
//        return isSectionHeaderPosition(position)
//                ? false
//                : mBaseAdapter.isEnabled(sectionedPositionToPosition(position));
//    }

    @Override
    public int getComponentTypeCount() {
        return mBaseAdapter.getComponentTypeCount() + 1; // the section headings
    }
    //todo
//    @Override
//    public boolean areAllItemsEnabled() {
//        return false;
//    }
//
//    @Override
//    public boolean hasStableIds() {
//        return mBaseAdapter.hasStableIds();
//    }

//    @Override
//    public boolean isEmpty() {
//        return mBaseAdapter.isEmpty();
//    }

    @Override
    public Component getComponent(int position, Component convertView, ComponentContainer parent) {
        if (isSectionHeaderPosition(position)) {
            Text view = (Text) convertView;
            if (view == null) {
                view = (Text) mLayoutScatter.parse(mSectionResourceId, parent, false);
            }
            view.setText(mSections.get(position).get().title.toString());
            return view;

        } else {
            return mBaseAdapter.getComponent(sectionedPositionToPosition(position), convertView, parent);
        }
    }
}